package com.base.dataStructure.linkedlist;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Iterator;

/**
 * @Author: hdhao
 * @Create: 2023/3/27 - 23:17
 * @Version: v1.0
 */
//双向环形链表
public class DoublyLoopLinkedListSentinel implements Iterable<Integer>{
    private Node sentinel = new Node(null,-1,null);

    public DoublyLoopLinkedListSentinel() {
        sentinel.prev = sentinel;
        sentinel.next = sentinel;
    }

    /**
     * 添加到第一个元素
     * @param value
     */
    public void addFirst(int value){
        Node a = sentinel;
        Node b = sentinel.next;
        Node added = new Node(a, value, b);
        a.next = added;
        b.prev = added;
    }

    /**
     * 添加元素到尾结点
     * @param value
     */
    public void addLast(int value){
        Node a = sentinel.prev;
        Node b = sentinel;
        Node added = new Node(a, value, b);
        a.next = added;
        b.prev = added;
    }

    /**
     * 删除第一个元素
     */
    public void removeFirst(){
        Node removed = sentinel.next;
        if (removed == sentinel){
            throw new RuntimeException("exception occurred");
        }
        Node a = sentinel;
        Node b = removed.next;
        a.next = b;
        b.prev = a;
    }

    /**
     * 删除最后一个元素
     */
    public void removeLast(){
        Node removed = sentinel.prev;
        if (removed == sentinel){
            throw new RuntimeException("exception occurred");
        }
        Node a = removed.prev;
        Node b = sentinel;
        a.next = b;
        b.prev = a;
    }

    /**
     * 根据值删除节点
     * @param value
     */
    public void removeByValue(int value){
        Node removed = findByValue(value);
        if (removed == null){
            throw new RuntimeException("exception occurred");
        }
        Node a = removed.prev;
        Node b = removed.next;
        a.next = b;
        b.prev = a;
    }

    /**
     * 根据值查找节点
     * @param value
     * @return
     */
    public Node findByValue(int value){
        Node p = sentinel.next;
        while (p!=sentinel){
            if (p.value == value){
                return p;
            }
            p = p.next;
        }
        return null;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = sentinel.next;
            @Override
            public boolean hasNext() {
                return p!=sentinel;
            }

            @Override
            public Integer next() {
                int value = p.value;
                p = p.next;
                return value;
            }
        };
    }

    @Data
    @AllArgsConstructor
    private static class Node{
        Node prev;
        int value;
        Node next;
    }
}
